﻿using BestTrader.Cms.Core.Models;
using BestTrader.Cms.Core.Options;
using BestTrader.Cms.IServices;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using Qiniu.Http;
using Qiniu.Storage;
using Qiniu.Util;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;

namespace estTrader.Cms.Services
{
    /// <summary>
    /// 七牛云 上传
    /// </summary>
    public class QiniuService: IQiniuService
    {
        private Config _config;
        protected QiniuOption _option;
        public QiniuService(IOptionsSnapshot<QiniuOption> options)
        {
            _option = options.Get("QINIU");


            // ZoneID zoneId = ZoneID.CN_East; 
            // [CN_East:华东] [CN_South:华南] [CN_North:华北] [US_North:北美]
            // USE_HTTPS = (true|false) 是否使用HTTPS
            
            _config = new Config {
                Zone = Zone.ZoneCnSouth,
                UseHttps = _option.UseHttps
            };
            ////Config.SetZone(zoneId, USE_HTTPS);
            //// AK = ACCESS_KEY
            //// USE_HTTPS = (true|false) 是否使用HTTPS
            //// 使用前请确保AK和BUCKET正确，否则此函数会抛出异常(比如code612/631等错误)
            //Config.AutoZone(_option.AccessKey, _option.Bucket, _option.UseHttps);
        }

        private Mac GetMac() {
            // 生成(上传)凭证时需要使用此Mac
            // 这个示例单独使用了一个Settings类，其中包含AccessKey和SecretKey
            // 实际应用中，请自行设置您的AccessKey和SecretKey

            Mac mac = new Mac(_option.AccessKey, _option.SecretKey);

            return mac;
        }

        private String GetPolicy(String saveKey) {
            // 上传策略，参见 
            // https://developer.qiniu.com/kodo/manual/put-policy
            PutPolicy putPolicy = new PutPolicy();
            // 如果需要设置为"覆盖"上传(如果云端已有同名文件则覆盖)，请使用 SCOPE = "BUCKET:KEY"
            //var saveKey = $"BestTraderImage/{ DateTime.Now.ToString("yyyy/MM/dd") }/{ fileName ?? _option.Bucket }";
            //putPolicy.Scope = $"{ _option.Bucket }:{ saveKey }";
            putPolicy.Scope = string.Format("{0}", _option.Bucket);

            // 上传策略有效期(对应于生成的凭证的有效期)          
            putPolicy.SetExpires(3600);

            // 上传到云端多少天后自动删除该文件，如果不设置（即保持默认默认）则不删除
            //putPolicy.DeleteAfterDays = 1;

            // 生成上传凭证，参见
            // https://developer.qiniu.com/kodo/manual/upload-token            
            return putPolicy.ToJsonString();
        }

        public byte[] StreamToBytes(Stream stream)
        {
            byte[] bytes = new byte[stream.Length];
            stream.Read(bytes, 0, bytes.Length);
            // 设置当前流的位置为流的开始
            stream.Seek(0, SeekOrigin.Begin);
            return bytes;
        }

        /// 将 byte[] 转成 Stream

        public Stream BytesToStream(byte[] bytes)
        {
            Stream stream = new MemoryStream(bytes);
            return stream;
        }

        /// <summary>
        /// 获取七牛云的Token
        /// </summary>
        public string GetToken(String fileName = "")
        {
            var mac = GetMac();
            var jstr = GetPolicy(fileName);

            return Auth.CreateUploadToken(mac, jstr);
        }

        /// <summary>
        /// 实现将文件上传到七牛云
        /// </summary>
        /// <param name="stream">文件流</param>
        /// <param name="fileName">文件名称</param>
        /// <returns></returns>
        public async Task<UploadQiniuData> UploadFileAsync(IFormFile file)
        {
            //获取上传凭证
            var saveKey = $"BestTraderImage/{ DateTime.Now.ToString("yyyy/MM/dd") }/{ file.FileName }";
            var uploadToken = GetToken(saveKey);
            var extra = new PutExtra();
            var stream = StreamToBytes(file.OpenReadStream());

            var um = new UploadManager(_config);
            var data = await um.UploadData(stream, _option.AccessKey, uploadToken, extra);

            var result = JsonConvert.DeserializeObject<UploadQiniuData>(data.Text);
            result.Key = $"{_option.BaseUrl}{result.Key}";

            return result;
        }

        public async Task<List<UploadQiniuData>> UploadFilesAsync(IFormFileCollection files)
        {
            var result = new List<UploadQiniuData>();
            foreach (var file in files)
            {
                //获取上传凭证
                var saveKey = $"BestTraderImage/{ DateTime.Now.ToString("yyyy/MM/dd") }/{ file.FileName }";
                var uploadToken = GetToken(saveKey);
                var extra = new PutExtra();
                var stream = StreamToBytes(file.OpenReadStream());

                var um = new UploadManager(_config);
                var data = await um.UploadData(stream, _option.AccessKey, uploadToken, extra);

                var json = JsonConvert.DeserializeObject<UploadQiniuData>(data.Text);
                json.Key = $"{_option.BaseUrl}{json.Key}";
                result.Add(json);
            }

            return result;
        }


        //public List<Object> UploadQiniu()
        //{
        //    Mac mac = new Mac(_option.AccessKey, _option.SecretKey); // AK SK使用
        //    PutPolicy putPolicy = new PutPolicy();
        //    putPolicy.Scope = _option.Bucket;
        //    string token = Auth.CreateUploadToken(mac, putPolicy.ToJsonString());//token生成
        //    IFormFileCollection files = Request.Form.Files;
        //    Config config = new Config()
        //    {
        //        Zone = Zone.ZONE_CN_East,
        //        UseHttps = true
        //    };
        //    var res = Request.Form.ToArray();

        //    FormUploader upload = new FormUploader(config);
        //    HttpResult result = new HttpResult();
        //    List<Object> list = new List<Object>();
        //    foreach (IFormFile file in files)//获取多个文件列表集合
        //    {
        //        if (file.Length > 0)
        //        {
        //            var _fileName = ContentDispositionHeaderValue
        //                            .Parse(file.ContentDisposition)
        //                            .FileName
        //                            .Trim('"');
        //            var _qiniuName = appSettings.qiniuupload.prefixPath + "/" + DateTime.Now.ToString("yyyyMMddHHmmssffffff") + _fileName;//重命名文件加上时间戳
        //            Stream stream = file.OpenReadStream();
        //            result = upload.UploadStream(stream, _qiniuName, token, null);
        //            if (result.Code == 200)
        //            {
        //                list.Add(new { fileName = _fileName, qiniuName = _qiniuName, uploadTime = DateTime.Now, Remark = res.First(p => p.Key == _fileName).Value[0] });
        //            }
        //            else
        //            {
        //                throw new Exception(result.RefText);//上传失败错误信息
        //            }
        //        }
        //    }
        //    return list;
        //}
    }
}
